use proc_macro::TokenStream;
use syn::parse_macro_input;

macro_rules! convert_expand_result {
    ($e:expr) => {
        match $e {
            Ok(val) => val.into(),
            Err(err) => err.into_compile_error().into(),
        }
    };
}

#[proc_macro_attribute]
pub fn impl_api(_: TokenStream, item: TokenStream) -> TokenStream {
    let item = parse_macro_input!(item as syn::Item);
    let expand_result = carpet_expand::handler_attribute::impl_api_expand(item);
    convert_expand_result!(expand_result)
}

#[proc_macro_attribute]
pub fn impl_handler(_attr: TokenStream, item: TokenStream) -> TokenStream {
    let item = parse_macro_input!(item as syn::Item);
    let expand_result = carpet_expand::handler_attribute::impl_handler_expand(item);
    convert_expand_result!(expand_result)
}

#[proc_macro_derive(Handler)]
pub fn handler_derive(input: TokenStream) -> TokenStream {
    let expand_result = carpet_expand::handler_derive::expand(&mut parse_macro_input!(input));
    convert_expand_result!(expand_result)
}

#[proc_macro_attribute]
pub fn multipart_dto(_attr: TokenStream, item: TokenStream) -> TokenStream {
    let item = parse_macro_input!(item as syn::Item);
    let expand_result = carpet_expand::dto_attribute::multipart_expand(item);
    convert_expand_result!(expand_result)
}

#[proc_macro_attribute]
pub fn text_dto(_attr: TokenStream, item: TokenStream) -> TokenStream {
    let item = parse_macro_input!(item as syn::Item);
    let expand_result = carpet_expand::dto_attribute::text_expand(item);
    convert_expand_result!(expand_result)
}

#[proc_macro_attribute]
pub fn state(_attr: TokenStream, item: TokenStream) -> TokenStream {
    let item = parse_macro_input!(item as syn::Item);
    let expand_result = carpet_expand::state_attribute::impl_state_expand(item);
    convert_expand_result!(expand_result)
}
